from rest_framework.response import Response
from rest_framework import viewsets, status

from apps.inform.models import Inform,InformRead
from .serializers import InformSerializer,ReadInformSerializer
from django.db.models import Q
from django.db.models import Prefetch

class InformViewSet(viewsets.ModelViewSet):
    queryset = Inform.objects.all() #定义了视图集将操作的数据集。表示将操作所有 Inform 模型实例。
    serializer_class = InformSerializer #定义了序列化

#通知列表
#1.infrom.public = True
#2.inform.departments包含了用户所在的部门
#3.inform.author = request.user

    def get_queryset(self): #用于定义和返回一个查询集:从数据库获取对象合集
        #多个条件的并关系查找，需要用Q表达式
        #优化查询：预先从数据库中检索与通知相关的阅读记录，以减少查询次数
            # select_related优化查询，在同一数据库查询中获取外键相关联的对象数据
            # prefetch_related:类似select_related，用于多对多关系和反向外键关系

        #distinct：删除重复的结果
        queryset = (self.queryset.select_related('author'). #author指当前模型(Inform)的外键字段author关联的OAUser模型，查询时会同时获得author信息
                    prefetch_related(Prefetch("reads",   #"reads"指的是当前模型(Inform)中的反向关系，关联到InformRead(该模型中有外键关联到Inform中，反向获取了该模型的外键)
                                            queryset=InformRead.objects.filter(user_id=self.request.user.uid)), 'departments') #过滤预取请求中与当前用户id匹配的记录
                                            .filter(Q(public=True)  #字段public公开的条件
                                                    | Q(departments=self.request.user.department) #属于当前部门
                                                    | Q(author=self.request.user)).distinct()) #通知发布者是本人
        # for inform in queryset:
        #     inform.is_read = InformRead.objects.filter(inform=inform,user=self.request.user).exists()
        return queryset

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        if instance.author.uid == request.user.uid:
            self.perform_destroy(instance)
            return Response(status=status.HTTP_204_NO_CONTENT)
        else:
            return Response(status=status.HTTP_401_UNAUTHORIZED)


    # 重写retrieve方法 :针对单个通知的get检索请求
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object() #获取请求的模型实例
        serializer = self.get_serializer(instance)
        data = serializer.data
        #双下划线 __ 来表示外键关系，inform__id 表示 InformRead 模型中的 inform 字段对应的 Inform 模型的 id 字段
        # 获取阅读数量:从阅读记录中筛选出id与当前通知模型id一致的记录并计数
        data['read_count'] = InformRead.objects.filter(inform__id=instance.id).count()
        return Response(data=data) #返回计数

from rest_framework.views import APIView
class ReadInformView(APIView):
    def post(self,request):
        serializer = ReadInformSerializer(data=request.data) #序列化验证
        if serializer.is_valid():
            inform_pk = serializer.validated_data.get('inform_pk') #从验证后的数据中获取通知的主键
            if InformRead.objects.filter(inform_id=inform_pk,user_id=request.user.uid).exists():#检查是否已存在该用户的阅读记录
                return Response()
            else:
                try:
                    InformRead.objects.create(inform_id=inform_pk, user_id=request.user.uid) #创建一个新的阅读记录
                except Exception as e:
                    print(e)
                    return Response(data={'detail':"阅读失败！"},status = status.HTTP_400_BAD_REQUEST)
                return Response()
        else:
            return Response(data={'detail': list(serializer.errors.values())[0][0]}, status=status.HTTP_400_BAD_REQUEST)


